﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.IO;
using __Able.Network.Utils;
using Org.Mentalis.Network.ProxySocket;
using __Able.Network;

namespace CCU
{
    class Dispatcher
    {
        /// <summary>
        /// 
        /// </summary>
        private const int PORT = 12345;

        static void Main(string[] args)
        {
            Dispatcher s = new Dispatcher();
            s.Start();
            Console.WriteLine("\r\nPress enter to exit...");
            Console.ReadLine();
        }

        public void Start()
        {
            Console.WriteLine("Please enter the IP address of the network adapter to listen on [use 0.0.0.0 to listen on all installed network adapters]:");
            IPAddress bindip;
            try
            {
                bindip = IPAddress.Parse(Console.ReadLine());
            }
            catch
            {
                Console.WriteLine("Invalid IP address!");
                return;
            }
            Console.WriteLine("Please enter the port to listen on [or 0 to automatically select one]:");
            int bindport;
            try
            {
                bindport = int.Parse(Console.ReadLine());
                if (bindport < IPEndPoint.MinPort || bindport > IPEndPoint.MaxPort)
                    throw new Exception();
            }
            catch
            {
                Console.WriteLine("Invalid port!");
                return;
            }
            Console.WriteLine("Press CTRL-BREAK to kill the server.");
            StartServer(new IPEndPoint(bindip, bindport));
        }

        public void StartServer(IPEndPoint ep)
        {
            ProxySocket s = new ProxySocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            s.Bind(ep);
            s.Listen(10);
            Console.WriteLine("Listening on " + s.LocalEndPoint.ToString());
            Socket ss;

            byte[] packetLengthBuffer = new byte[2];
            int ret;
            ushort packetLength;

            while (true)
            {
                ss = (Socket)s.Accept();
                Console.WriteLine("Incoming socket accepted.");
                Console.WriteLine("Receiving request...");
                ret = 0;
                packetLength = 0;

                ret = ss.Receive(packetLengthBuffer, 0, 2, SocketFlags.None);
                if (ret > 0)
                {
                    // 获得包的长度
                    packetLength = new ByteBuffer(packetLengthBuffer).GetUShort();
                    Console.WriteLine("Received a packet length {0}", packetLength);
                    IPAddress ip = IPAddress.Parse(((IPEndPoint)ss.RemoteEndPoint).Address.ToString());
                    Console.WriteLine("IP: {0}", ip.ToString());

                    byte[] _buf = new byte[packetLength];
                    ret = ss.Receive(_buf, 0, packetLength, SocketFlags.None);
                    if (ret > 0)
                    {
                        ByteBuffer buf = new ByteBuffer(_buf);

                        int hl = buf.GetUShort();
                        int pos = buf.Position;
                        Console.WriteLine("HeaderLength:\t{0}", hl);
                        Console.WriteLine("Sequence:\t{0}", buf.Get());
                        Console.WriteLine("ID:\t\t{0}", new Guid(buf.GetByteArray(16)).ToString());
                        Console.WriteLine("Version:\t{0}", BitConverter.ToString(buf.GetByteArray(4)));
                        Console.WriteLine("Token:\t\t{0}", buf.GetUShort());
                        Console.WriteLine("ModuleName:\t{0}", Util.GetString(buf.GetByteArray(hl + pos - buf.Position)));

                        Console.WriteLine("Body:\t\t{0}", Util.GetString(buf.GetByteArray(buf.Length - buf.Position - 1)));

                        Console.WriteLine("Tail:\t\t{0}", buf.Get());

                    }
                }
                if (ret == 0)
                {
                    Console.WriteLine("Client closed connection too soon.");
                    ss.Close();
                    break;
                }

                // Send HTTP reply
                Console.WriteLine("Sending reply...");

                string pdata = Console.ReadLine();
                while (pdata != "0")
                {
                    ret = 0;
                    try
                    {
                        while (ret != pdata.Length)
                        {
                            ret += ss.Send(Encoding.UTF8.GetBytes(pdata), ret, pdata.Length - ret, SocketFlags.None);
                        }
                        //ss.Shutdown(SocketShutdown.Both);
                        //ss.Close();
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Error while sending data to the client [" + e.Message + "].");
                        Console.WriteLine(e);
                    }
                    pdata = Console.ReadLine();
                }

                ss.Shutdown(SocketShutdown.Both);
                ss.Close();

                Console.WriteLine("Waiting for another connection...");
            }
        }
    }
}
